package com.vecspace.utils.log;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HLogger {
	private Logger log;
	
	private static HLogger defaultLogger;
	private static boolean cacheMsgInMem = true;
	static{
		defaultLogger = new HLogger("root");
	}
	public HLogger(){
		 
	}
	
	public HLogger(String appender){
		if("root".equals(appender) || appender== null || appender.length() == 0){
			log = LoggerFactory.getLogger("root");
		}else{
			log = LoggerFactory.getLogger(appender);
		}
	}
	
	public static HLogger DEFAULT(){
		return defaultLogger;
	}
	
	public static HLogger defaultLogger(){
		return defaultLogger;
	}

	private static Map<String, HLogger> loggers = new HashMap<>();
	
	public static HLogger getLog(String appender){
		HLogger logger = loggers.get(appender);
		if(logger == null) {
			synchronized (loggers) {
				logger = loggers.get(appender);
				if(logger == null) {					
					logger = new HLogger(appender);
					loggers.put(appender, logger);
				}
			}
		}
		return logger;
	}
	
	public boolean isDebugEnabled() {		
		return log.isDebugEnabled();
	}
	
	public boolean isErrorEnabled() {		 
		return log.isErrorEnabled();
	}
		
	public boolean isInfoEnabled() {
		return log.isInfoEnabled();
	}
	
	public boolean isTraceEnabled() {
		return log.isTraceEnabled();
	}
	
	public boolean isWarnEnabled() {
		return log.isWarnEnabled();
	}

	public void trace(Object message) {
		if(message != null) {
			if(message instanceof Exception){
				message = getStackTrace((Exception)message);
			}
			log.trace(message.toString());
			if(cacheMsgInMem && log.isTraceEnabled()) {
				HLoggerCache.putLog(message);
			}
		}
	}
	
	public void trace(Object message, Throwable t) {
		if(message!=null) {
			if(message instanceof Exception){
				message = getStackTrace((Exception)message);
			}
			log.trace(message.toString(), t);
			if(cacheMsgInMem && log.isTraceEnabled()) {
				HLoggerCache.putLog(message);
			}
		}
	}

	public void trace(String format, Object arg) {
		log.trace(format, arg);
		if(cacheMsgInMem && log.isTraceEnabled()) {
			String msg = format + "[" + arg + "]";
			HLoggerCache.putLog(msg);
		}
	}

	public void trace(String format, Object... args) {
		log.trace(format, args);
		if(cacheMsgInMem && log.isTraceEnabled()) {
			String msg = format + "[" + StringUtils.join(args, ", ")+"]";
			HLoggerCache.putLog(msg);
		}
	}
	

	public void debug(String format, Object arg) {
		log.debug(format, arg);
		if(cacheMsgInMem && log.isDebugEnabled()) {
			String msg = format + "[" + arg + "]";
			HLoggerCache.putLog(msg);
		}
	}

	public void debug(String format, Object... args) {
		log.debug(format, args);
		if(cacheMsgInMem && log.isDebugEnabled()) {
			String msg = format + "[" + StringUtils.join(args, ", ")+"]";
			HLoggerCache.putLog(msg);
		}
	}

	public void debug(Object message) {
		if(message == null) {
			return;
		}
		log.debug(message.toString());
		if(cacheMsgInMem && log.isDebugEnabled()) {
			HLoggerCache.putLog(message);
		}
	}
	
	public void debug(Object message, Throwable t) {
		if(message == null) {
			return;
		}
		log.debug(message.toString(), t);
		if(cacheMsgInMem && log.isDebugEnabled()) {
			HLoggerCache.putLog(message);
		}
	}
	

	public void info(Object message) {
		if(message != null) {
			if(message instanceof Exception){
				message = getStackTrace((Exception)message);
			}
			log.info(message.toString());
			if(cacheMsgInMem && log.isInfoEnabled()) {
				HLoggerCache.putLog(message);
			}
		}
	}
	
	public void info(String format, Object arg) {
		log.info(format, arg);
		if(cacheMsgInMem && log.isInfoEnabled()) {
			String msg = format + "[" + arg + "]";
			HLoggerCache.putLog(msg);
		}
	}

	public void info(String format, Object... args) {
		log.info(format, args);
		if(cacheMsgInMem && log.isInfoEnabled()) {
			String msg = format + "[" + StringUtils.join(args, ", ")+"]";
			HLoggerCache.putLog(msg);
		}
	}
	
	public void warn(String format, Object arg) {
		log.warn(format, arg);
		if(cacheMsgInMem && log.isWarnEnabled()) {
			String msg = format + "[" + arg + "]";
			HLoggerCache.putLog(msg);
		}
	}

	public void warn(String format, Object... args) {
		log.warn(format, args);
		if(cacheMsgInMem && log.isWarnEnabled()) {
			String msg = format + "[" + StringUtils.join(args, ", ")+"]";
			HLoggerCache.putLog(msg);
		}
	}

	public void warn(Object message) {
		if(message != null) {
			if(message instanceof Exception){
				message = getStackTrace((Exception)message);
			}
			log.warn(message.toString());
			if(cacheMsgInMem && log.isWarnEnabled()) {
				HLoggerCache.putLog(message);
			}
		}
	}

	public void warn(String message, Throwable t) {
		if(message != null) {			
			log.warn(message, t);
			if(cacheMsgInMem && log.isWarnEnabled()) {
				HLoggerCache.putLog(message);
			}
		}
	}

	public void error(String message) {
		if(message == null) {
			return;
		}
		log.error(message.toString());
		if(cacheMsgInMem && log.isErrorEnabled()) {
			HLoggerCache.putErrorLog(message);
			HLoggerCache.putLog(message);
		}
	}
	
	public void error(String format, Object arg) {
		log.error(format, arg);
		if(cacheMsgInMem && log.isErrorEnabled()) {
			String msg = format + "[" + arg + "]";
			HLoggerCache.putErrorLog(msg);
			HLoggerCache.putLog(msg);
		}
	}

	public void error(String format, Object... args) {
		log.error(format, args);
		if(cacheMsgInMem && log.isErrorEnabled()) {
			String msg = format + "[" + StringUtils.join(args, ", ")+"]";
			HLoggerCache.putErrorLog(msg);
			HLoggerCache.putLog(msg);
		}
	}
	
	public void error(Exception ex) {
		if(ex == null) {
			return;
		}
		
		String message = getStackTrace((Exception)ex);
		
		log.error(message.toString());
		if(cacheMsgInMem && log.isErrorEnabled()) {
			HLoggerCache.putErrorLog(message);
			HLoggerCache.putLog(message);
		}
	}
	
	public void error(String message, Throwable t) {
		if(message == null) {
			return;
		}
		log.error(message, t);
		if(cacheMsgInMem && log.isErrorEnabled()) {
			String message2 = getStackTrace((Exception)t);
			String msg = message +":"+ message2;
			HLoggerCache.putErrorLog(msg);
			HLoggerCache.putLog(msg);
		}
	}

	public void fatal(String message) {
		if(message == null) {
			return;
		}
		log.error(message);
		if(cacheMsgInMem) {
			HLoggerCache.putErrorLog(message);
			HLoggerCache.putLog(message);
		}
	}
	
	public void fatal(String message, Throwable t) {
		if(message == null) {
			return;
		}
		log.error(message, t);
		if(cacheMsgInMem) {
			String message2 = getStackTrace((Exception)t);
			String msg = message +":"+ message2;
			HLoggerCache.putErrorLog(msg);
			HLoggerCache.putLog(msg);
		}
	}
	
	public void println(Object message){
		System.out.println(message.toString());
	}
		
	/**将exception的错误栈信息输出为字符串信息
	 * 
	 * @param e
	 * @return
	 * @version 1.0
	 * @author wanghua
	 */
	public static String getStackTrace(Exception e) {
        try {
            StringWriter sw = new StringWriter();  
            PrintWriter pw = new PrintWriter(sw);  
            e.printStackTrace(pw);            
            String str = sw.toString();
            pw.close();
            sw.close();
            return str;
        } catch (Exception e2) {  
            return "bad getErrorInfoFromException:"+e.toString();  
        }  
    }

	public boolean isCacheMsgInMem() {
		return cacheMsgInMem;
	}

	public void setCacheMsgInMem(boolean cacheMsgInMem) {
		HLogger.cacheMsgInMem = cacheMsgInMem;
	}
	
	
}
